<!-- HTML header for doxygen 1.8.3.1-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.3.1"/>
<title>Sifteo SDK: Scripting</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="doxygen-style-overrides.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<center>
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Sifteo SDK" src="sdk_logo.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">
   &#160;<span id="projectnumber">v1.0.0</span>
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
</center>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.3.1 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Home</span></a></li>
      <li class="current"><a href="pages.html"><span>Guides</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="annotated.html"><span>Reference</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Classes</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Namespaces</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(8)"><span class="SelectionMark">&#160;</span>Groups</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(9)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Scripting </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Automate, introspect and debug apps via Lua scripting</p>
<h1>Running Lua code</h1>
<p>The Sifteo platform simulator <em>Siftulator</em> includes scripting support, via an embedded <a href="http://www.lua.org/">Lua</a> interpreter. This scripting support is intended primarily for automated testing, and as a way to interface emulated Sifteo games with the outside world for debugging, testing, and exploration.</p>
<p>Within Siftulator, there are two ways to use Lua scripting.</p>
<h2>Shell mode</h2>
<p>You can start Siftulator with the <code>-e</code> command line option. This instructs Siftulator to run the specified Lua script, in the main thread, <em>instead</em> of starting the usual simulation environment.</p>
<p>In this mode, the Siftulator binary acts as a very basic shell around the Lua interpreter. By creating objects like <b>System()</b> and <b>Frontend()</b>, the script can then explicitly set up the parts of the simulation that it needs.</p>
<p>This mode is used internally, for unit-testing of Siftulator and the Sifteo Cube hardware model. It may also be suitable for <em>black box</em> testing of Sifteo games which have no debug instrumentation at all. These external tests can inspect the display contents of each cube, and they may read or write any memory in the system. They also have some limited capacity for interacting with the hardware simulation or with the UI Frontend.</p>
<p>Sample shell-mode script:</p>
<div class="fragment"><div class="line">-- Lua script file</div>
<div class="line"></div>
<div class="line">print <span class="stringliteral">&quot;Hello&quot;</span></div>
<div class="line"></div>
<div class="line">sys = System()</div>
<div class="line">fe = Frontend()</div>
<div class="line">c = Cube(0)</div>
<div class="line"></div>
<div class="line">sys:setOptions{numCubes=1}</div>
<div class="line"></div>
<div class="line">sys:init()</div>
<div class="line">fe:init()</div>
<div class="line">sys:start()</div>
<div class="line"></div>
<div class="line">print(<span class="keywordtype">string</span>.format(&quot;Radio address: %s&quot;, c:getRadioAddress()))</div>
<div class="line"></div>
<div class="line">repeat</div>
<div class="line">    fe:postMessage(<span class="keywordtype">string</span>.format(&quot;Hello from Lua! (%.2f sec)&quot;,          </div>
<div class="line">        sys:vclock()))</div>
<div class="line">    print(<span class="keywordtype">string</span>.format(&quot;LCD: %10d pixels, %10d frames&quot;,</div>
<div class="line">        c:lcdPixelCount(), c:lcdFrameCount()))</div>
<div class="line">until not fe:runFrame()</div>
<div class="line"></div>
<div class="line">sys:exit()</div>
<div class="line">fe:exit()</div>
</div><!-- fragment --><h2>Inline scripting</h2>
<p>In this mode, script fragments are interleaved with normal C++ game code, using some macro, linker, and runtime tricks. It all starts with the <a class="el" href="group__macros.html#ga7a08279d8529b1eb2d374ee61f50849c" title="Inline emulator scripting, for automated testing and more.">SCRIPT()</a> and <a class="el" href="group__macros.html#gaae31453655b2aac2b521a9e198a78863" title="Like SCRIPT(), but this variant supports format specifiers.">SCRIPT_FMT()</a> macros, which allow inline execution of Lua code in your game, with limited ways for game code and Lua code to exchange data.</p>
<p>It is often useful to include out-of-line Lua code via require(). All inline scripting runs in its own context, distinct from the context used by shell-mode scripting. This single context is shared between all blocks of inline Lua code. The code is always parsed and run in the order that the enclosing C++ code runs, so these opening declarations commonly happen at the top of main().</p>
<p>Sample in-line scripting code:</p>
<div class="fragment"><div class="line"><span class="comment">// Example fragments of inline scripting from C++</span></div>
<div class="line"></div>
<div class="line"><a class="code" href="group__macros.html#ga7a08279d8529b1eb2d374ee61f50849c" title="Inline emulator scripting, for automated testing and more.">SCRIPT</a>(LUA,</div>
<div class="line">    package.path = package.path .. <span class="stringliteral">&quot;;scripts/?.lua&quot;</span></div>
<div class="line">    require(<span class="stringliteral">&#39;my-test-library&#39;</span>)</div>
<div class="line">);</div>
<div class="line"></div>
<div class="line"><span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> i = 0; i &lt; 10; ++i)</div>
<div class="line">    <a class="code" href="group__macros.html#ga7a08279d8529b1eb2d374ee61f50849c" title="Inline emulator scripting, for automated testing and more.">SCRIPT</a>(LUA, invokeTest());</div>
<div class="line"></div>
<div class="line"><a class="code" href="group__macros.html#ga7a08279d8529b1eb2d374ee61f50849c" title="Inline emulator scripting, for automated testing and more.">SCRIPT</a>(LUA, System():setAssetLoaderBypass(<span class="keyword">true</span>));</div>
<div class="line"><a class="code" href="group__macros.html#ga7a08279d8529b1eb2d374ee61f50849c" title="Inline emulator scripting, for automated testing and more.">SCRIPT</a>(LUA, Cube(0):saveScreenshot(<span class="stringliteral">&quot;myScreenshot.png&quot;</span>));</div>
<div class="line"><a class="code" href="group__macros.html#ga7a08279d8529b1eb2d374ee61f50849c" title="Inline emulator scripting, for automated testing and more.">SCRIPT</a>(LUA, Cube(0):testScreenshot(<span class="stringliteral">&quot;myScreenshot.png&quot;</span>));</div>
<div class="line"></div>
<div class="line"><a class="code" href="group__macros.html#gaae31453655b2aac2b521a9e198a78863" title="Like SCRIPT(), but this variant supports format specifiers.">SCRIPT_FMT</a>(LUA, <span class="stringliteral">&quot;Frontend():postMessage(&#39;Power is &gt;= %d&#39;)&quot;</span>, 9000);</div>
<div class="line"></div>
<div class="line"><span class="keywordtype">int</span> luaGetInteger(<span class="keyword">const</span> <span class="keywordtype">char</span> *expr) {</div>
<div class="line">    <span class="keywordtype">int</span> result;</div>
<div class="line">    <a class="code" href="group__macros.html#gaae31453655b2aac2b521a9e198a78863" title="Like SCRIPT(), but this variant supports format specifiers.">SCRIPT_FMT</a>(LUA, <span class="stringliteral">&quot;Runtime():poke(%p, %s)&quot;</span>, &amp;result, expr);</div>
<div class="line">    <span class="keywordflow">return</span> result;</div>
<div class="line">}</div>
<div class="line"></div>
<div class="line"><span class="keywordtype">void</span> luaSetInteger(<span class="keyword">const</span> <span class="keywordtype">char</span> *varName, <span class="keywordtype">int</span> value) {</div>
<div class="line">    <a class="code" href="group__macros.html#gaae31453655b2aac2b521a9e198a78863" title="Like SCRIPT(), but this variant supports format specifiers.">SCRIPT_FMT</a>(LUA, <span class="stringliteral">&quot;%s = %d&quot;</span>, varName, value);</div>
<div class="line">}</div>
</div><!-- fragment --><h2>Interfacing with the outside world</h2>
<p>The Lua <a href="http://www.lua.org/manual/5.1/manual.html#5.7">Input / Output library</a> is available, for reading or writing files on disk..</p>
<p>Additionally, environment variables (via <code>os.getenv</code>) are a convenient way to read parameters at any point, whether you're using shell mode or inline scripting.</p>
<h1>Execution Environment</h1>
<h2>Standard Lua packages</h2>
<p>The Lua interpreter is based on <a href="http://www.lua.org/manual/5.1/">Lua 5.1</a>.</p>
<p>Standard Lua libraries:</p>
<ul>
<li><a href="http://www.lua.org/manual/5.1/manual.html#5.1">Basic Functions</a></li>
<li><a href="http://www.lua.org/manual/5.1/manual.html#5.3">Modules</a></li>
<li><a href="http://www.lua.org/manual/5.1/manual.html#5.5">Table Manipulation</a></li>
<li><a href="http://www.lua.org/manual/5.1/manual.html#5.7">Input and Output Facilities</a></li>
<li><a href="http://www.lua.org/manual/5.1/manual.html#5.8">Operating System Facilities</a></li>
<li><a href="http://www.lua.org/manual/5.1/manual.html#5.4">String manipulation</a></li>
<li><a href="http://www.lua.org/manual/5.1/manual.html#5.6">Mathematical functions</a></li>
<li><a href="http://www.lua.org/manual/5.1/manual.html#5.9">Debug Library</a></li>
</ul>
<p>Built-in extension modules:</p>
<ul>
<li><a href="http://bitop.luajit.org/api.html">BitOp Library</a></li>
</ul>
<h2>System object</h2>
<p>This is a singleton object which represents the simulated state of the system, at a high level.</p>
<h3>System()</h3>
<p>The constructor for System does not actually allocate any resources in Siftulator, it just allocates a Lua object which can then be used as a proxy for the simulated system state. Takes no parameters.</p>
<h3>System():setOptions{ <em>key</em> = <em>value</em>, ... }</h3>
<p>Set one or more key-value pairs which describe global simulation options.</p>
<table class="doxtable">
<tr>
<th>Option </th><th>Meaning</th></tr>
<tr>
<td><code>numCubes</code> </td><td>Number of cubes to simulate. Also set by the <code>-n</code> command line option. </td></tr>
<tr>
<td><code>turbo</code> </td><td>Boolean value. If false, the simulation runs as close to real-time as possible. If true, the simulation runs as fast as possible. </td></tr>
<tr>
<td><code>paintTrace</code> </td><td>Boolean value. If true, dump detailed Paint Controller logs. </td></tr>
<tr>
<td><code>radioTrace</code> </td><td>Boolean value. If true, log the contents of all radio packets. </td></tr>
<tr>
<td><code>svmTrace</code> </td><td>Boolean value. If true, log all executed SVM instructions. </td></tr>
<tr>
<td><code>svmFlashStats</code> </td><td>Boolean value. If true, dump statistics about flash memory usage. </td></tr>
<tr>
<td><code>svmStackMonitor</code> </td><td>Boolean value. If true, monitor SVM stack usage. </td></tr>
</table>
<h3>System():numCubes()</h3>
<p>Retrieve the current number of simulated cubes. This value can be set with <code>System():setOptions{numCubes=N}</code>, the <code>-n</code> command line option, or keyboard commands in the UI.</p>
<h3>System():init()</h3>
<p>Initialize the simulation subsystem. This includes the simulated Cubes, radio, and Base. The system must be initialized before most other methods are invoked. Note that this function is only needed when using scripting in <em>shell mode</em>. With inline scripting, you're running from within the simulated environment, so it by necessity is already initialized.</p>
<h3>System():start()</h3>
<p>Begin running the simulation, on a separate thread pool. Like init(), this is only applicable in <em>shell mode</em>. Other modules, such as Frontend, may be initialized between calling init() and start().</p>
<h3>System():exit()</h3>
<p>Halt the simulation, and free resources associated with it. Only useful in <em>shell mode</em>.</p>
<h3>System():setAssetLoaderBypass( <em>true</em> | <em>false</em> )</h3>
<p>Enable or disable <em>asset loader bypass</em> mode. In this mode, all asset downloads will appear to complete instantaneously. Instead of fully simulating the asset download process using Siftulator's hardware-accurate simulation engine, the assets are decompressed using native code and written directly to the Cube's simulated Asset Flash memory.</p>
<p>Note that your game code must still go through the same procedure to install assets; this just reduces the amount of time taken by the install process, making for a quicker dev/test cycle.</p>
<h3>System():vclock()</h3>
<p>Return the current <em>virtual time</em>, in seconds. This is the elapsed time, from the perspective of the simulated system. If the simulation is running at 50% real-time, for example, this value will increase at a rate of 0.5 virtual seconds per real second.</p>
<p>The virtual clock's resolution is approximately 60 nanoseconds.</p>
<h3>System():vsleep( <em>seconds</em> )</h3>
<p>Block the caller for the specified number of seconds, in <em>virtual time</em>. This is not an exact delay. It tries to sleep for the minimum amount of time which is greater than or equal to the specified duration. The Lua scripting engine is not precisely synchronized with the simulation engine, however.</p>
<h3>System():sleep( <em>seconds</em> )</h3>
<p>Block the caller for a specified number of real wall-clock seconds. This depends on the underlying operating system's sleep primitive, and the accuracy will vary depending on the platform.</p>
<h2>Frontend object</h2>
<p>This is a singleton object which represents the graphical frontend to Siftulator. In <em>shell mode</em>, the frontend must be explicitly initialized, and your script is responsible for running the frontend's main loop. With <em>inline</em> scripting, the frontend is run automatically on a separate thread.</p>
<h3>Frontend()</h3>
<p>The constructor for Frontend does not actually allocate any resources in Siftulator, it just allocates a Lua object which can then be used as a proxy for the grapical frontend state. Takes no parameters.</p>
<h3>Frontend():init()</h3>
<p>Set up the frontend. Creates a window, allocates GPU resources, etc. If any of this fails, init() will throw a Lua error.</p>
<h3>Frontend():exit()</h3>
<p>Terminate the graphical frontend. Closes the window, frees textures, and so on.</p>
<h3>Frontend():runFrame()</h3>
<p>Run the frontend's main loop, for a single frame. This automatically includes a frame-rate throttling feature, which dynamically decreases the frame rate during periods of no interaction.</p>
<p>Returns <em>true</em> if the frontend should still be running or <em>false</em> if the user has asked Siftulator to exit.</p>
<h3>Frontend():postMessage( <em>string</em> )</h3>
<p>Post a message string to the frontend's heads-up display. A posted message will display for a few seconds before automatically clearing. Posting a new message will instantly replace the previously posted message.</p>
<p>This method is suitable for either transient messages, or for information displays that stay visible for long periods of time.</p>
<h2>Cube object</h2>
<p>The Cube object is an accessor for a single simulated Sifteo Cube. This is a lightweight Lua object which acts as a proxy for the internal object which simulates a single cube.</p>
<h3>Cube( <em>number</em> )</h3>
<p>The constructor for Cube does not actually allocate any resources in Siftulator, it just allocates a Lua object and binds it to a particular cube ID. Cube IDs are zero-based.</p>
<h3>Cube(N):reset()</h3>
<p>Reset the state of this cube's simulation. Equivalent to removing and reinserting the cube's batteries.</p>
<h3>Cube(N):lcdFrameCount()</h3>
<p>Read this cube's LCD frame counter. Every time the cube hardware finishes drawing one full frame, this counter increments. It is a 32-bit unsigned integer, which will wrap around.</p>
<p>When comparing two frame counts, the easiest way to handle wrap-around is to ensure that you're using 32-bit arithmetic as well. For example:</p>
<div class="fragment"><div class="line">local c = Cube(0)</div>
<div class="line">local count = c:lcdFrameCount()</div>
<div class="line">local framesRendered = bit.band(count - lastCount, 0xFFFFFFFF)</div>
<div class="line">lastCount = count</div>
</div><!-- fragment --><h3>Cube(N):lcdPixelCount()</h3>
<p>Read this cube's LCD pixel counter. This is much like lcdFrameCount(), except instead of incrementing once per completed frame, it increments every time a pixel is written to the display hardware. The pixel count will change continuously while a frame is being rendered.</p>
<p>This is also an unsigned 32-bit integer. Note that integer wraparound could occur in as little as 1 hour.</p>
<h3>Cube(N):saveScreenshot( <em>filename</em> )</h3>
<p>Save a screenshot of this cube, to a 128x128 pixel PNG file with the given name.</p>
<h3>Cube(N):testScreenshot( <em>filename</em>, <em>tolerance</em> = 0 )</h3>
<p>Capture a screenshot of this cube, and compare it to an existing 128x128 pixel PNG file with the given name.</p>
<p>If the images match, returns nothing. If there was an error opening the reference image file, raises a Lua error.</p>
<p>If the reference image was loaded successfully, this function compares the reference to the actual screenshot, pixel by pixel. By default, an exact match is required. Even a slight difference in the 16-bit value of a pixel would cause a pixel mismatch.</p>
<p>The optional <em>tolerance</em> parameter can be used to allow inexact matches. The images are still compared pixel-by-pixel. For each difference, an error value is computed:</p>
<ol type="1">
<li>The two pixels, reference and actual, are both converted to 24-bit (8 bit per channel) color.</li>
<li>For each of the three color channels: The two pixel values are subtracted, and that result is squared.</li>
<li>The squared differences for each of the three channels are summed.</li>
</ol>
<p>This is equivalent to the Mean Squared Error for that single pixel, multiplied by three. The computed error value is always an integer. If this error is less than or equal to <em>tolerance</em>, the comparison continues successfully. If it is greater, a pixel mismatch occurs.</p>
<p>In the event of a pixel mismatch, this function returns five parameters:</p>
<table class="doxtable">
<tr>
<th>Position </th><th>Name </th><th>Meaning</th></tr>
<tr>
<td>1 </td><td>x </td><td>Zero-based X coordinate </td></tr>
<tr>
<td>2 </td><td>y </td><td>Zero-based Y coordinate </td></tr>
<tr>
<td>3 </td><td>lcdPixel </td><td>Actual pixel on the LCD, as a 16-bit RGB565 value </td></tr>
<tr>
<td>4 </td><td>refPixel </td><td>Reference pixel from the provided PNG, after conversion to 16-bit RGB565 format </td></tr>
<tr>
<td>5 </td><td>errValue </td><td>The actual error value for this pixel (greater than <em>tolerance</em>) </td></tr>
</table>
<h3>Cube(N):getNeighborID()</h3>
<p>Returns the low-level <em>neighbor ID</em> for a cube. This is the 8-bit number used internally to identify a cube to its neighbors. The low 5 bits of this number will match the cube's CubeID in userspace. (The top three bits are reserved.) It will be zero if the cube is not sending any neighbor signal.</p>
<h3>Cube(N):xbPoke( <em>address</em>, <em>byte</em> )</h3>
<p>Write one byte to the cube's Video RAM, at the specified byte address. Byte addresses must be in the range [0, 1023]. Out-of-range addresses will wrap around.</p>
<h3>Cube(N):xwPoke( <em>address</em>, <em>word</em> )</h3>
<p>Write one 16-bit word to the cube's Video RAM, at the specified word address. Word addresses must be in the range [0, 511]. Out-of-range addresses will wrap around.</p>
<h3>Cube(N):xbPeek( <em>address</em> )</h3>
<p>Read one byte from the cube's Video RAM, at the specified byte address. Byte addresses must be in the range [0, 1023]. Out-of-range addresses will wrap around.</p>
<h3>Cube(N):xwPeek( <em>address</em> )</h3>
<p>Read one 16-bit word to the cube's Video RAM, at the specified word address. Word addresses must be in the range [0, 511]. Out-of-range addresses will wrap around.</p>
<h3>Cube(N):fbPoke( <em>address</em>, <em>byte</em> )</h3>
<p>Write one byte to the cube's Asset Flash memory, at the specified byte address.</p>
<h3>Cube(N):fwPoke( <em>address</em>, <em>word</em> )</h3>
<p>Write one 16-bit word to the cube's Asset Flash memory, at the specified word address.</p>
<h3>Cube(N):fbPeek( <em>address</em> )</h3>
<p>Read one byte from the cube's Asset Flash memory, at the specified byte address.</p>
<h3>Cube(N):fwPeek( <em>address</em> )</h3>
<p>Read one 16-bit word to the cube's Asset Flash memory, at the specified word address.</p>
<h2>Runtime object</h2>
<p>This is a singleton object which represents the simulated state of the <a class="el" href="execution_env.html">Execution Environment</a>.</p>
<h3>Runtime()</h3>
<p>The constructor for Runtime does not actually allocate any resources in Siftulator, it just allocates a Lua object which can then be used as a proxy for the simulated runtime state. Takes no parameters.</p>
<h3>Runtime():poke( <em>address</em>, <em>word</em> )</h3>
<p>Write a 32-bit word into RAM, at the specified virtual address. When using <em>inline</em> scripting, this address is equivalent to the value of a C++ pointer to integer or unsigned integer.</p>
<p>If the virtual address is invalid, raises a Lua error.</p>
<h3>Runtime():peek( <em>address</em> )</h3>
<p>Read a 32-bit word from RAM, at the specified virtual address. When using <em>inline</em> scripting, this address is equivalent to the value of a C++ pointer to integer or unsigned integer.</p>
<p>If the virtual address is invalid, raises a Lua error.</p>
<h3>Runtime():faultString( <em>code</em> )</h3>
<p>Given a numeric fault code, returns a string describing that fault.</p>
<h3>Runtime():formatAddress( <em>address</em> )</h3>
<p>Given a virtual address uses the currently loaded symbol tables, if any, to format the address as a string. Even if no suitable symbols can be found, this function will return a readable hexadecimal offset.</p>
<h3>Runtime():onFault( <em>code</em> )</h3>
<p>By default this function does nothing, but it can be overridden in order to handle VM faults in a special way. By returning 'true', the fault is considered to be <em>handled</em> and program execution will continue. You may wish to use functions like branch() to modify control flow first. By returning 'false', the default fault handler will proceed to run, and the application will be terminated.</p>
<p>You can use this to build unit tests that expect a fault to occur:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;sifteo.h&gt;</span></div>
<div class="line"><span class="keyword">using namespace </span>Sifteo;</div>
<div class="line"></div>
<div class="line"><span class="keywordtype">void</span> <a class="code" href="group__macros.html#ga1b173d22e57d9395897acbd8de62d505" title="Disable automatic inlining for one function.">NOINLINE</a> buggyFunction()</div>
<div class="line">{</div>
<div class="line">    <a class="code" href="group__macros.html#ga3577749fb48d57a158b8ac1a0b3ab57e" title="Smart printf-like logging macro.">LOG</a>(<span class="stringliteral">&quot;About to crash...\n&quot;</span>);</div>
<div class="line">    *(<span class="keyword">volatile</span> <span class="keywordtype">int</span>*)0 = 0;</div>
<div class="line">    <a class="code" href="group__macros.html#ga3577749fb48d57a158b8ac1a0b3ab57e" title="Smart printf-like logging macro.">LOG</a>(<span class="stringliteral">&quot;Shouldn&#39;t get here!\n&quot;</span>);</div>
<div class="line">}</div>
<div class="line"></div>
<div class="line"><span class="keywordtype">void</span> <a class="code" href="group__macros.html#ga1b173d22e57d9395897acbd8de62d505" title="Disable automatic inlining for one function.">NOINLINE</a> handler()</div>
<div class="line">{</div>
<div class="line">    <a class="code" href="group__macros.html#ga3577749fb48d57a158b8ac1a0b3ab57e" title="Smart printf-like logging macro.">LOG</a>(<span class="stringliteral">&quot;Recovering from the fault...\n&quot;</span>);</div>
<div class="line">    <span class="comment">// This returns from buggyFunction()&#39;s stack frame.</span></div>
<div class="line">}</div>
<div class="line"></div>
<div class="line"><span class="keywordtype">void</span> main()</div>
<div class="line">{</div>
<div class="line">    <a class="code" href="group__macros.html#gaae31453655b2aac2b521a9e198a78863" title="Like SCRIPT(), but this variant supports format specifiers.">SCRIPT_FMT</a>(LUA, <span class="stringliteral">&quot;pHandler = 0x%x&quot;</span>, &amp;handler);</div>
<div class="line">    <a class="code" href="group__macros.html#ga7a08279d8529b1eb2d374ee61f50849c" title="Inline emulator scripting, for automated testing and more.">SCRIPT</a>(LUA,</div>
<div class="line"></div>
<div class="line">        <span class="comment">// On faults in Siftulator, transfer flow control to the C++ handler()</span></div>
<div class="line">        <span class="keyword">function</span> Runtime:onFault(code)</div>
<div class="line">            print(<span class="stringliteral">&quot;Fault handled in Lua: &quot;</span> .. rt:faultString(code))</div>
<div class="line">            rt:branch(pHandler)</div>
<div class="line">            <span class="keywordflow">return</span> <span class="keyword">true</span></div>
<div class="line">        end</div>
<div class="line"></div>
<div class="line">        <span class="comment">// Creating an instance installs the callback</span></div>
<div class="line">        rt = Runtime()</div>
<div class="line">    );</div>
<div class="line"></div>
<div class="line">    <span class="comment">// We expect this function to fail</span></div>
<div class="line">    buggyFunction();</div>
<div class="line">}</div>
</div><!-- fragment --><h3>Runtime():getPC()</h3>
<p>Return the virtual CPU's program counter. Only recommended for use with inline scripting. This will reflect the state of the program at the point where it was interrupted to run the inline script.</p>
<h3>Runtime():getSP()</h3>
<p>Return the virtual CPU's stack pointer register.</p>
<h3>Runtime():getFP()</h3>
<p>Return the virtual CPU's frame pointer register. This will point to an 8-word structure containing state to be restored by the VM at the next return instruction.</p>
<h3>Runtime():getGPR( <em>n</em> )</h3>
<p>Return the value of a general purpose register in the virtual CPU. N must be between 0 and 7, inclusive.</p>
<h3>Runtime():branch( <em>pc</em> )</h3>
<p>Issue a branch to the specified code pointer. Only recommended for use with inline scripting. This is equivalent to an unconditional branch instruction that happened to execute at the exact place and time where the VM was stopped to run the script.</p>
<h3>Runtime():setGPR( <em>n</em>, <em>value</em> )</h3>
<p>Change the value of a general purpose register in the virtual CPU. N must be between 0 and 7, inclusive.</p>
<h3>Runtime():runningVolume()</h3>
<p>Return the filesystem's block code for the volume containing our current ELF binary.</p>
<h3>Runtime():previousVolume()</h3>
<p>Return the filesystem's block code for the volume which executed this one.</p>
<h3>Runtime():virtToFlashAddr( <em>virtual address</em> )</h3>
<p>Convert an SVM virtual address to a physical Flash memory address, using the currently active mappings. If this VA is not mapped, returns zero.</p>
<h3>Runtime():flashToVirtAddr( <em>flash address</em> )</h3>
<p>Convert a physical Flash memory address to an SVM virtual address. If the supplied flash address is not part of any virtual address space, returns zero.</p>
<h2>Filesystem object</h2>
<p>This is a singleton object which can be used to script the Base's filesystem.</p>
<p>This is the same filesystem which can be accessed with the SDK's <a class="el" href="group__filesystem.html">Filesystem</a> objects. By scripting the filesystem, you can automatically test portions of your game which depend on persistent data storage.</p>
<h3>Filesystem()</h3>
<p>The constructor for Filesystem does not actually allocate any resources in Siftulator, it just allocates a Lua object which can then be used as a proxy for the filesystem layer in the Base's operating system. Takes no parameters.</p>
<h3>Filesystem():newVolume( <em>type</em>, <em>payload data</em>, <em>type-specific data</em> = "", <em>parent</em> = 0 )</h3>
<p>Creates, writes, and commits a new <a class="el" href="class_sifteo_1_1_volume.html" title="A coarse-grained region of external memory.">Sifteo::Volume</a> in the filesystem. The specified <em>type</em> is the same 16-bit type code used by the <a class="el" href="class_sifteo_1_1_volume.html#a51e316c5824f5032be1ad59e90ed74ed" title="Enumeration of common volume types.">Sifteo::Volume::Type</a> enumeration. <em>Payload data</em> is a string with binary data to load the Volume with.</p>
<p>The <em>type-specific data</em> parameter is an optional binary string, used by some volume types. Omitting this parameter is equivalent to passing in the empty string.</p>
<p>The <em>parent</em> parameter is a block code for another volume that is hierarchically above this new volume. If the parent volume is deleted, this volume (and its children, if any) are also deleted.</p>
<p>On success, returns the volume's block code. This is an opaque identifier which is indirectly related to the identity of a <a class="el" href="class_sifteo_1_1_volume.html" title="A coarse-grained region of external memory.">Sifteo::Volume</a> object. It is guaranteed to be nonzero.</p>
<p>On error (out of filesystem space), returns no results.</p>
<h3>Filesystem():listVolumes()</h3>
<p>List all volumes on the filesystem. Returns an array of block codes.</p>
<h3>Filesystem():deleteVolume( <em>block code</em> )</h3>
<p>Mark a volume as deleted. If the provided block code is not valid, raises a Lua error.</p>
<h3>Filesystem():volumeType( <em>block code</em> )</h3>
<p>Given a volume's block code, return the associated 16-bit type identifier. If the provided block code is not valid, raises a Lua error.</p>
<h3>Filesystem():volumeParent( <em>block code</em> )</h3>
<p>Given a volume's block code, return its parent's block code, if any. If this volume is not parented to another, returns zero.</p>
<h3>Filesystem():volumePayload( <em>block code</em> )</h3>
<p>Given a volume's block code, return its payload data as a string.</p>
<h3>Filesystem():simulatedBlockEraseCounts()</h3>
<p>Return an array of simulated erase counts for every 64K block in the Base's flash memory. This data is tracked by Siftulator's simulation engine itself.</p>
<p>This can be used to measure how much flash wear and tear is being caused by a particular test.</p>
<p>If Siftulator is running with persistent flash storage (<code>-F</code> command line option), the erase counts are also persisted in the same file.</p>
<h3>Filesystem():rawRead( <em>address</em>, <em>count</em> )</h3>
<p>Read <em>count</em> bytes from the raw Flash device, starting at the specified device address. Returns the data as a string.</p>
<h3>Filesystem():rawWrite( <em>address</em>, <em>data</em> )</h3>
<p>Write the string <em>data</em> to the raw Flash device, starting at <em>address</em>. Does not automatically erase the device. This effectively performs a bitwise AND of the supplied data with the existing contents of the device.</p>
<p>Use this function with care. Remember you're bypassing the filesystem and writing to low-level flash memory. If you use rawWrite(), you likely must also use rawErase() and invalidateCache() correctly as well.</p>
<h3>Filesystem():rawErase( <em>address</em> )</h3>
<p>Erase one 64 kB block of the raw Flash device, starting at the specified block-aligned address.</p>
<h3>Filesystem():invalidateCache()</h3>
<p>Force the system to discard or reload all cached Flash data. Any memory blocks which are still in use will be overwritten with freshly-loaded data, while unused cached memory blocks are simply discarded.</p>
<p>In addition to the systemwide block cache, this flushes other special-purpose caches used by the filesystem.</p>
<h3>Filesystem():setCallbacksEnabled( <em>true</em> | <em>false</em> )</h3>
<p>This enables a set of Lua callbacks which fire on any low-level access to flash memory. These can be used for low-level tracing and debugging, or for collecting metrics on how memory is being used during a particular operation.</p>
<p>By default these callbacks are disabled for performance reasons. When enabled, the system will call onRawRead(), onRawWrite(), and onRawErase() during the corresponding low-level events. These functions all have default implementations which do nothing. They are meant to be overridden by user code.</p>
<p>For example:</p>
<div class="fragment"><div class="line"><span class="keyword">function</span> Filesystem:onRawRead(addr, data)</div>
<div class="line">    print(<span class="keywordtype">string</span>.format(&quot;Read %08x, %d bytes&quot;, addr, <span class="keywordtype">string</span>.len(data)))</div>
<div class="line">end</div>
<div class="line"></div>
<div class="line">function Filesystem:onRawWrite(addr, data)</div>
<div class="line">    print(<span class="keywordtype">string</span>.format(&quot;Write %08x, %d bytes&quot;, addr, <span class="keywordtype">string</span>.len(data)))</div>
<div class="line">end</div>
<div class="line"></div>
<div class="line">function Filesystem:onRawErase(addr)</div>
<div class="line">    print(<span class="keywordtype">string</span>.format(&quot;Erase %08x&quot;, addr))</div>
<div class="line">end</div>
<div class="line"></div>
<div class="line">fs = Filesystem()</div>
<div class="line">fs:setCallbacksEnabled(true)</div>
</div><!-- fragment --><p>This overrides the three callback methods on Filesystem, then enables those callbacks. Any Flash memory operations after this point will be accompanied by logging.</p>
<p>The addresses supplied are physical flash addresses. Where applicable, you can translate them back to virtual addresses (a.k.a C++ pointers) using <code>Runtime():flashToVirtAddr()</code>.</p>
<h3>Filesystem():readMetadata( <em>volume</em>, <em>key</em> )</h3>
<p>Read a metadata value from an ELF binary identified by a volume bock code. Returns the raw binary contents of the metadata key as a string, or nil if the key does not exist. Note that metadata values may be padded at the end.</p>
<h3>Filesystem():readObject( <em>volume</em>, <em>key</em> )</h3>
<p>Read a StoredObject from a particular ELF binary's object storage. Returns the raw binary contents of the object as a string, an empty string if the object has been deleted, or nil if the object doesn't exist in the filesystem at all.</p>
<h3>Filesystem():writeObject( <em>volume</em>, <em>key</em>, <em>data</em> )</h3>
<p>Write a StoredObject to a particular ELF binary's object storage. Automatically causes filesystem garbage collection if we're low on space. Raises a Lua error if we're actually out of storage space. </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.3.1-->
<!-- start footer part -->
    <hr class="footer"/>
    <address class="footer">
        <p><a href="http://sifteo.com">Sifteo</a> SDK v1.0.0 <small>(see <a href="https://developers.sifteo.com/sifteosdk">all versions</a>)</small></p>
        <p>Last updated Wed Mar 27 2013, by <a href="http://www.stack.nl/~dimitri/doxygen">Doxygen</a></p>
    </address>
</body>
</html>
